import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkToc from 'remark-toc';
import remarkGfm from 'remark-gfm';
import _ from 'lodash';
import { type Node } from 'unified/lib';

export type AstNode = Node & {
  children?: AstNode[];
  depth?: number;
  value?: string;
  ordered?: boolean;
  lang?: string;
  checked?: boolean;
  identifier?: string;
  label?: string;
  title?: string;
  url?: string;
  alt?: string;
  __no?: number;
};

type ParseOptions = {
  unposition?: boolean;
};

/**
 * @see https://www.npmjs.com/package/@textlint/markdown-to-ast
 */
export function parse(text: string, options: ParseOptions = {}): AstNode {
  const remark = unified().use(remarkParse).use(remarkToc).use(remarkGfm);
  const node = remark.parse(text) as AstNode;
  if (options.unposition) {
    unposition(node);
  }
  return node;
}

function unposition(node: AstNode) {
  delete node.position;
  _.forEach(node.children, unposition);
}

export function findDefinitions(node: AstNode): AstNode[] {
  const definitions: AstNode[] = [];
  findDefinitionsRecursice(node, definitions);
  return definitions;

  function findDefinitionsRecursice(node: AstNode, list: AstNode[]) {
    if (node.type === 'definition') {
      list.push(node);
    }
    _.forEach(node.children, (child) => findDefinitionsRecursice(child, list));
  }
}
